﻿using db_manage.dll.db;
using db_manage.model;
using db_manage.model.db;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;

namespace db_manage.dll.manage
{
    /// <summary>
    /// 执行业务
    /// </summary>
    public partial class manage
    {
        /// <summary>
        /// 执行脚本
        /// </summary>
        /// <param name="sql_list"></param>
        public static string sql_exec(List<sql_fileinfo> sql_list)
        {
            return manage.db_task(new req_db_task()
            {
                exec_action = (db_info) =>
                {
                    var now_sql_list = sql_list;
                    //-从最后一个成功版本之后开始执行
                    var last_successinfo_sql = "select max(vernum) vernum from db_manage_record where updatestatus=1";
                    var last_dbinfo = db_factory.Instance.sql_query<db_manage_record>(db_info, last_successinfo_sql).FirstOrDefault();
                    if (last_dbinfo != null
               && (manage.db_manage_config.db_config_exec.begin_last_successnum ?? false)
               && !(now_sql_list?.Any(x => x.vernum == -1) ?? false))
                    {
                        //从最后一个成功的版本之后开始执行
                        now_sql_list = now_sql_list.Where(x => x.vernum > (last_dbinfo.vernum ?? 0)).ToList();
                    }
                    //-执行脚本
                    if (now_sql_list?.Any() ?? false)
                    {
                        now_sql_list.ForEach(x =>
                            {
                                db_info.vernum = x.vernum;
                                db_info.updatetime = DateTime.Now;
                                db_info.updatestatus = null;
                                db_manage_record olddbinfo = null;
                                if (x.vernum != -1)
                                {
                                    olddbinfo = db_factory.Instance.sql_query<db_manage_record>(db_info, $"select * from db_manage_record where vernum={x.vernum}").FirstOrDefault();
                                }

                                if (olddbinfo == null || olddbinfo.updatestatus != 1 || olddbinfo.vernum == -1)//已经成功的就不再执行,-1表示单独执行脚本，可重复执行
                                {
                                    var infosql = (olddbinfo == null || olddbinfo.vernum == -1) ?
                                    $" insert into db_manage_record(vernum, updatetime,updatestatus, remark,taketime,sqlstr)  values(@vernum, @updatetime,@updatestatus,@remark,@taketime,@sqlstr) " :
                                    $" update db_manage_record set updatetime=@updatetime,updatestatus=@updatestatus,remark=@remark,taketime=@taketime where vernum=@vernum ";
                                    try
                                    {
                                        var sqls = Regex.Split(x.sql, "\r\n[G|g][O|o][\r\n]*");//数据库本身不支持GO，在这里进行替换分割
                                        foreach (var itemsql in sqls)
                                        {
                                            if (string.IsNullOrEmpty(itemsql.Trim()))
                                            {
                                                continue;
                                            }
                                            db_factory.Instance.sql_exec(db_info, itemsql);
                                        }
                                        //添加记录
                                        db_record_set(db_info, true, null, null, db_info.vernum == -1 ? x.sql : null);//单次执行记录脚本
                                        db_factory.Instance.sql_exec(db_info, infosql, db_info);
                                    }
                                    catch (Exception ex)
                                    {
                                        db_record_set(db_info, false, $"错误版本：{x.vernum},错误原因：{ex.Message}", ex);
                                        //添加记录
                                        db_factory.Instance.sql_exec(db_info, infosql, db_info);
                                        if (!(manage.db_manage_config.db_config_exec.ingore_fail ?? false))//不忽略错误则停止，否则继续执行
                                        {
                                            return;
                                        }
                                    }
                                }

                            });
                    }
                    else
                    {
                        db_info.updatestatus = 1;
                        db_info.remark = "无需操作";
                    }
                }
            });
        }
    }
}
